﻿using MediatR;
using ProduceBasicData.Api.Application.Command.Weather;
using ProduceBasicData.Domain.Weather;
using ProduceBasicData.ErrorCode;
using ProduceBasicData.Infrastructure;
using ProduceBasicData.Infrastructure.Implement;
using ProduceBasicData.Infrastructure.Interface;
using System.Text.Json;

namespace ProduceBasicData.Api.Application.Handler.Weather
{
    /// <summary>
    /// 天气预警生成处理器（集成高德API，关联生产数据生成预警）
    /// </summary>
    public class GenerateWeatherAlertCommandHandler : IRequestHandler<GenerateWeatherAlertCommand, ApiResult<List<WeatherAlert>>>
    {
        private readonly HttpClient _httpClient;
        private readonly IWeatherApiSettings _weatherApiSettings;
        private readonly IBaseRespository<WeatherAlert> _weatherAlertRepo;
        //private readonly BaseRespository<ProductionPlan> _productionPlanRepo;
        //private readonly IBaseRespository<Device> _deviceRepo;
        private readonly ILogger<GenerateWeatherAlertCommandHandler> _logger;

        public GenerateWeatherAlertCommandHandler(
            IHttpClientFactory httpClientFactory,
            IWeatherApiSettings weatherApiSettings,
            IBaseRespository<WeatherAlert> weatherAlertRepo,
            //IBaseRespository<ProductionPlan> productionPlanRepo,
            //IBaseRespository<Device> deviceRepo,
            ILogger<GenerateWeatherAlertCommandHandler> logger)
        {
            _httpClient = httpClientFactory.CreateClient("WeatherApi") ?? throw new ArgumentNullException(nameof(httpClientFactory));
            _weatherApiSettings = weatherApiSettings ?? throw new ArgumentNullException(nameof(weatherApiSettings));
            _weatherAlertRepo = weatherAlertRepo ?? throw new ArgumentNullException(nameof(weatherAlertRepo));
            //_productionPlanRepo = productionPlanRepo ?? throw new ArgumentNullException(nameof(productionPlanRepo));
            //_deviceRepo = deviceRepo ?? throw new ArgumentNullException(nameof(deviceRepo));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        public async Task<ApiResult<List<WeatherAlert>>> Handle(GenerateWeatherAlertCommand request, CancellationToken cancellationToken)
        {
            var result = new ApiResult<List<WeatherAlert>>
            {
                Code = ApiEnum.Failed,
                Msg = "生成天气预警失败",
                Data = new List<WeatherAlert>()
            };

            try
            {
                // 1. 校验输入（必须提供城市编码或经纬度）
                if (string.IsNullOrWhiteSpace(request.CityCode) && (!request.Latitude.HasValue || !request.Longitude.HasValue))
                {
                    result.Msg = "参数错误：需提供城市编码或经纬度";
                    return result;
                }

                // 2. 调用高德天气API获取数据
                AmapWeatherResponse weatherData;
                if (!string.IsNullOrWhiteSpace(request.CityCode))
                {
                    weatherData = await QueryWeatherByCityCodeAsync(request.CityCode, cancellationToken);
                }
                else
                {
                    weatherData = await QueryWeatherByCoordinatesAsync(
                        request.Latitude!.Value,
                        request.Longitude!.Value,
                        cancellationToken);
                }

                // 3. 校验API返回有效性
                if (weatherData.Status != "1" || weatherData.Lives == null || !weatherData.Lives.Any())
                {
                    result.Msg = $"天气API返回无效数据：{weatherData.Info}";
                    return result;
                }

                // 4. 生成生产关联预警
                var alerts = await GenerateProductionAlertsAsync(weatherData, request, cancellationToken);
                if (alerts.Any())
                {
                    // 5. 持久化预警到数据库
                    await _weatherAlertRepo.AddRangeAsync(alerts);
                    result.Data = alerts;
                    result.Code = ApiEnum.Failed;
                    result.Msg = $"成功生成{alerts.Count}条生产关联预警";
                }
                else
                {
                    result.Code = ApiEnum.Success;
                    result.Msg = "当前天气未触发生产预警规则";
                }

                return result;
            }
            catch (HttpRequestException ex)
            {
                _logger.LogError(ex, "高德天气API请求失败");
                result.Msg = "天气API网络异常，请稍后重试";
                return result;
            }
            catch (JsonException ex)
            {
                _logger.LogError(ex, "天气数据解析失败");
                result.Msg = "天气数据格式错误，API响应异常";
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "生成天气预警时发生未预期错误");
                result.Msg = "系统异常，生成预警失败";
                return result;
            }
        }

        /// <summary>通过城市编码查询高德天气</summary>
        private async Task<AmapWeatherResponse> QueryWeatherByCityCodeAsync(string cityCode, CancellationToken cancellationToken)
        {
            var requestUrl = $"{_weatherApiSettings.BaseUrl}?key={_weatherApiSettings.ApiKey}" +
                            $"&city={cityCode}&extensions=all&output=json";
            _logger.LogDebug("调用高德天气API（城市编码）：{Url}", requestUrl);

            var response = await _httpClient.GetAsync(requestUrl, cancellationToken);
            response.EnsureSuccessStatusCode();

            var json = await response.Content.ReadAsStringAsync(cancellationToken);
            return JsonSerializer.Deserialize<AmapWeatherResponse>(json, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            }) ?? new AmapWeatherResponse();
        }

        /// <summary>通过经纬度查询高德天气</summary>
        private async Task<AmapWeatherResponse> QueryWeatherByCoordinatesAsync(double lat, double lon, CancellationToken cancellationToken)
        {
            var requestUrl = $"{_weatherApiSettings.BaseUrl}?key={_weatherApiSettings.ApiKey}" +
                            $"&location={lon},{lat}&extensions=all&output=json";
            _logger.LogDebug("调用高德天气API（经纬度）：{Url}", requestUrl);

            var response = await _httpClient.GetAsync(requestUrl, cancellationToken);
            response.EnsureSuccessStatusCode();

            var json = await response.Content.ReadAsStringAsync(cancellationToken);
            return JsonSerializer.Deserialize<AmapWeatherResponse>(json, new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            }) ?? new AmapWeatherResponse();
        }

        /// <summary>生成生产关联预警（结合生产计划、设备数据）</summary>
        private async Task<List<WeatherAlert>> GenerateProductionAlertsAsync(
            AmapWeatherResponse weatherData,
            GenerateWeatherAlertCommand request,
            CancellationToken cancellationToken)
        {
            var alerts = new List<WeatherAlert>();
            var liveWeather = weatherData.Lives[0]; // 取实时天气

            // ---- 规则1：高温预警（关联设备耐温 + 生产计划）----
            if (double.TryParse(liveWeather.Temperature, out double temp) && temp >= 35)
            {
                var highTempAlert = new WeatherAlert
                {
                    WeatherType = "高温",
                    AlertLevel = GetHighTemperatureLevel(temp),
                    AffectRange = "全厂区设备与人员",
                    Suggestion = GetHighTemperatureSuggestion(temp),
                    GenerateTime = DateTime.Now,
                    ProcessStatus = AlertProcessStatus.Pending,
                    Remark = $"城市：{liveWeather.City}，温度：{temp}℃（自动生成）"
                };

                //// 关联生产计划（若有）
                //if (request.ProductionPlanId.HasValue)
                //{
                //    var plan = await _productionPlanRepo.GetByIdAsync(request.ProductionPlanId.Value);
                //    if (plan != null)
                //    {
                //        highTempAlert.ProductionPlanId = plan.Id;
                //        highTempAlert.RelevantProcess = plan.WorkType;

                //        // 额外逻辑：户外作业提升预警等级
                //        if (plan.WorkType.Contains("户外"))
                //        {
                //            highTempAlert.AffectRange = $"生产计划「{plan.PlanName}」（户外作业）";
                //            highTempAlert.AlertLevel = AlertLevel.Orange;
                //        }

                //        // 关联设备（若生产计划有绑定设备）
                //        if (plan.RelatedDeviceIds.Any())
                //        {
                //            var devices = await _deviceRepo.GetListAsync(d => plan.RelatedDeviceIds.Contains(d.Id));
                //            var overTempDevices = devices.Where(d => temp < d.MinTemperature || temp > d.MaxTemperature).ToList();
                //            if (overTempDevices.Any())
                //            {
                //                highTempAlert.AffectRange += $", 设备{string.Join(",", overTempDevices.Select(d => d.DeviceName))}";
                //                highTempAlert.Suggestion += $"\n- 停止设备{string.Join(",", overTempDevices.Select(d => d.DeviceName))}运行";
                //            }
                //        }
                //    }
                //}

                alerts.Add(highTempAlert);
            }

            // ---- 规则2：暴雨预警（关联物流 + 户外生产）----
            if (liveWeather.Weather.Contains("暴雨") || liveWeather.Weather.Contains("大暴雨"))
            {
                var rainAlert = new WeatherAlert
                {
                    WeatherType = "暴雨",
                    AlertLevel = AlertLevel.Orange,
                    AffectRange = "物流运输、户外作业区",
                    Suggestion = "暂停户外作业，检查厂区排水，调整物流计划为室内仓储",
                    GenerateTime = DateTime.Now,
                    ProcessStatus = AlertProcessStatus.Pending,
                    Remark = $"城市：{liveWeather.City}，天气：{liveWeather.Weather}（自动生成）"
                };

                //// 关联生产计划（若有）
                //if (request.ProductionPlanId.HasValue)
                //{
                //    var plan = await _productionPlanRepo.GetByIdAsync(request.ProductionPlanId.Value);
                //    if (plan != null)
                //    {
                //        rainAlert.ProductionPlanId = plan.Id;
                //        rainAlert.RelevantProcess = plan.WorkType;

                //        // 额外逻辑：物流/户外计划特殊处理
                //        if (plan.WorkType.Contains("物流") || plan.WorkType.Contains("户外"))
                //        {
                //            rainAlert.Suggestion = $"暂停生产计划「{plan.PlanName}」的户外/物流环节，转移至室内";
                //        }
                //    }
                //}

                alerts.Add(rainAlert);
            }

            return alerts;
        }

        /// <summary>根据温度确定高温预警等级</summary>
        private AlertLevel GetHighTemperatureLevel(double temp) =>
            temp >= 40 ? AlertLevel.Red :
            temp >= 37 ? AlertLevel.Orange :
            AlertLevel.Yellow;

        /// <summary>根据温度生成高温建议</summary>
        private string GetHighTemperatureSuggestion(double temp) =>
            temp >= 40 ? "立即停止所有户外作业，启动防暑应急预案，开放全部降温点" :
            temp >= 37 ? "减少户外作业时间（每小时休息15分钟），加强设备散热监控" :
            "增加巡检频率，提供防暑饮品，避开12:00-15:00高温时段作业";

        #region 高德天气API响应模型（内部类）
        private class AmapWeatherResponse
        {
            public string Status { get; set; } = string.Empty; // 1=成功，0=失败
            public string Info { get; set; } = string.Empty;   // 错误信息
            public List<AmapLiveWeather> Lives { get; set; } = new(); // 实时天气
        }

        private class AmapLiveWeather
        {
            public string City { get; set; } = string.Empty;    // 城市名称
            public string Weather { get; set; } = string.Empty; // 天气描述
            public string Temperature { get; set; } = string.Empty; // 温度(℃)
        }
        #endregion
    }
}
